1. Technical Field
Embodiments of the present invention generally relate to the use of locks in multi-threaded execution environments. More particularly, embodiments relate to the use of component-specific locks that can be disclaimed, or “backed out” of, by their owning threads and subsequently reclaimed in the order in which they were disclaimed.
2. Discussion
Modern software is typically built from components, wherein it can be advantageous to eliminate the need for individual components to be aware of each other's inner workings. The components may reside, however, within a process in which threads holding locks (e.g., thread-safety synchronization objects) can transition program control from one component to another component. Accordingly, the thread-safety aspects of the various software components can become complex.
In particular, components that maintain thread-safe data protected by locks may be at risk in scenarios where those components are free to invoke each other's routines. For example, “deadlocks” can arise when threads holding locks on behalf of one component call into other components, acquire further locks, and then invoke the first component again. This situation can lead to lock acquisitions that are out of the normal order otherwise imposed by each component for any given set of locks. In this scenario, any two threads may be likely to deadlock, sooner or later.
To avoid the deadlock problem, some developers might design their components so as to release any locks acquired on behalf of one component prior to invoking the routines of another component. Conventional locks, however, are not intended to be, or easily, used in such a way. Indeed, locks typically lend themselves to being held throughout a given procedure performed on a given data set. A data set that is protected by a lock may not be amenable to routines that process information across that data set while calling out to other components during that processing. To implement deadlock safety in such a scenario, the lock could be released and reacquired while the data set is traversed. This approach, in turn, can lead to race conditions, typically in unexpected situations where one thread begins accessing the data set while another thread is performing such a release/reacquire cycle.